using System;
using System.Diagnostics;
using System.IO;
using AutoBuild.Core.Framework;
using Machine.Specifications;
using Rhino.Mocks;
using Rhino.Mocks.Constraints;

namespace AutoBuild.Specs.Core.Framework
{

    [Subject(typeof(ProcessExecutor))]
    public class the_expected_process_gets_executed : ProcessExecutorSpec
    {
        
         Because of = () => Subject.Execute(new ProcessStartInfo
                                                          {
                                                              FileName = "cmd",
                                                              Arguments = "/c echo Foo Bar",
                                                              CreateNoWindow = true,
                                                              UseShellExecute = false,
                                                              RedirectStandardOutput = true,
                                                          });

        It there_is_no_error = () => _console.WasNotCalled(x => x.Error(null), c => c.IgnoreArguments());

        It the_command_output_is_written_to_the_console =
                        () => _console.WasCalled(x => x.Info(Arg<string>.Matches(Text.StartsWith("Foo Bar"))));



    }

    [Subject(typeof(ProcessExecutor))]
    public class when_stderr_is_redirected_error_shows_on_console : ProcessExecutorSpec
    {

        Because of = () => Subject.Execute(new ProcessStartInfo
                                            {
                                                FileName = "cmd",
                                                Arguments = "/c echo Foo Bar 1>&2",
                                                CreateNoWindow = true,
                                                UseShellExecute = false,
                                                RedirectStandardError = true,
                                            });
        It the_command_error_is_written_to_the_console = 
            () => _console.WasCalled(x => x.Error(Arg<string>.Matches(Text.StartsWith("Foo Bar"))));

    }


    [Subject(typeof(ProcessExecutor))]
    public class when_stdout_is_redirected_shell_execute_needs_to_be_true : ProcessExecutorSpec
    {
        static Exception Exception;

        private Because of = () =>
                             Exception = Catch.Exception(() =>
                                                         Subject.Execute(new ProcessStartInfo
                                                                             {
                                                                                 RedirectStandardOutput = true,
                                                                                 UseShellExecute = true
                                                                             })
                                             );

        private It throws_an_invalid_operation_exception = 
            () => Exception.ShouldBeOfType<InvalidOperationException>();
    }

    [Subject(typeof(ProcessExecutor))]
    public class when_there_is_a_exception_it_can_be_handeled_manually : ProcessExecutorSpec
    {
        private static Exception Exception;

        private Because of = () =>
                             Exception = Catch.Exception(() => Subject.Execute(new ProcessStartInfo(""), true));

        private It has_the_exception = () => Exception.ShouldNotBeNull();
    }

    //--------------------------------------------------------- 
    public abstract class ProcessExecutorSpec : Specification<ProcessExecutor>
    {
        protected static IConsole _console;
        
        private Establish context = () =>
                                        {
                                            _console = Mock<IConsole>();
                                            Subject = new ProcessExecutor(_console);
                                        };

    }
}